﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace Xray.Common
{
    /// <summary>
    /// provides a wrapper for the WCF host
    /// </summary>
    /// <typeparam name="TContract">the interface for the host to use</typeparam>
    public class HostWrapper<TContract> : IDisposable
    {
        private readonly ServiceHost _host;
        private readonly TContract _instance;

        /// <summary>
        /// create an instance of the WCF host
        /// </summary>
        /// <param name="instance">the instance of the service to be hosted in WCF</param>
        /// <param name="baseAddress">the Uri of the service</param>
        public HostWrapper(TContract instance, Uri baseAddress)
        {        
            _host = new ServiceHost(instance, baseAddress);
            
            ServiceMetadataBehavior smb = 
                new ServiceMetadataBehavior
                {
                    HttpGetEnabled = true,
                    MetadataExporter = {PolicyVersion = PolicyVersion.Default}
                };

            _host.Description.Behaviors.Add(smb);
            _host.Open();
            _instance = instance;
        }

        /// <summary>
        /// provides the current instance of the service being hosted
        /// </summary>
        /// <returns></returns>
        public TContract HostInstance()
        {
            return _instance; 
        }

        /// <summary>
        /// Close the host
        /// </summary>
        public void Close()
        {
            try
            {
                if (_host.State == CommunicationState.Opened)
                {
                    _host.Close();
                }
            }
            catch (Exception)
            {
                _host.Abort();
            }
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Close();
        }
    }
}